[bits 32]
section .text

%define MAGIC 0x20250601

%define TRUE 1
%define FALSE 0

%macro INTERRUPT_VECTOR 2
interrupt_%1_handler:
    %ifn %2 
        push MAGIC ; 没有错误码那就压入魔数占位
    %endif
    push %1 ; 压入中断向量
    jmp interrupt_entry
%endmacro

code_selector equ (1 << 3)
data_selector equ (2 << 3)

extern handler_table

interrupt_entry:

    ; 保存寄存器
    push ds
    push es
    push fs
    push gs
    pusha

    ; 从 vm86 模式恢复
    mov ax, data_selector
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov eax, [esp + 12 * 4]

    push eax ; 压入中断号 方便调试

    ; 进入对应的 handler
    call [handler_table + eax * 4]

extern task_signal

global interrupt_exit
interrupt_exit:

    ; 跳过压入的中断向量
    add esp, 4

    ; 恢复保存的寄存器
    popa
    pop gs
    pop fs
    pop es
    pop ds

    ; 跳过中断向量和 error code
    add esp, (4 * 2)
    iret

INTERRUPT_VECTOR 0x00, FALSE
INTERRUPT_VECTOR 0x01, FALSE
INTERRUPT_VECTOR 0x02, FALSE
INTERRUPT_VECTOR 0x03, FALSE
INTERRUPT_VECTOR 0x04, FALSE
INTERRUPT_VECTOR 0x05, FALSE
INTERRUPT_VECTOR 0x06, FALSE
INTERRUPT_VECTOR 0x07, FALSE
INTERRUPT_VECTOR 0x08, TRUE
INTERRUPT_VECTOR 0x09, FALSE
INTERRUPT_VECTOR 0x0A, TRUE
INTERRUPT_VECTOR 0x0B, TRUE
INTERRUPT_VECTOR 0x0C, TRUE
INTERRUPT_VECTOR 0x0D, TRUE
INTERRUPT_VECTOR 0x0E, TRUE
INTERRUPT_VECTOR 0x0F, FALSE
INTERRUPT_VECTOR 0x10, FALSE

INTERRUPT_VECTOR 0x11, TRUE
INTERRUPT_VECTOR 0x12, FALSE
INTERRUPT_VECTOR 0x13, FALSE
INTERRUPT_VECTOR 0x14, FALSE
INTERRUPT_VECTOR 0x15, FALSE
INTERRUPT_VECTOR 0x16, FALSE
INTERRUPT_VECTOR 0x17, FALSE
INTERRUPT_VECTOR 0x18, FALSE
INTERRUPT_VECTOR 0x19, FALSE
INTERRUPT_VECTOR 0x1A, FALSE
INTERRUPT_VECTOR 0x1B, FALSE
INTERRUPT_VECTOR 0x1C, FALSE
INTERRUPT_VECTOR 0x1D, FALSE
INTERRUPT_VECTOR 0x1E, FALSE
INTERRUPT_VECTOR 0x1F, FALSE

INTERRUPT_VECTOR 0x20, FALSE
INTERRUPT_VECTOR 0x21, FALSE
INTERRUPT_VECTOR 0x22, FALSE
INTERRUPT_VECTOR 0x23, FALSE
INTERRUPT_VECTOR 0x24, FALSE
INTERRUPT_VECTOR 0x25, FALSE
INTERRUPT_VECTOR 0x26, FALSE
INTERRUPT_VECTOR 0x27, FALSE
INTERRUPT_VECTOR 0x28, FALSE
INTERRUPT_VECTOR 0x29, FALSE
INTERRUPT_VECTOR 0x2A, FALSE
INTERRUPT_VECTOR 0x2B, FALSE
INTERRUPT_VECTOR 0x2C, FALSE
INTERRUPT_VECTOR 0x2D, FALSE
INTERRUPT_VECTOR 0x2E, FALSE
INTERRUPT_VECTOR 0x2F, FALSE

section .data
global handler_entry_table

handler_entry_table:
    dd interrupt_0x00_handler
    dd interrupt_0x01_handler
    dd interrupt_0x02_handler
    dd interrupt_0x03_handler
    dd interrupt_0x04_handler
    dd interrupt_0x05_handler
    dd interrupt_0x06_handler
    dd interrupt_0x07_handler
    dd interrupt_0x08_handler
    dd interrupt_0x09_handler
    dd interrupt_0x0A_handler
    dd interrupt_0x0B_handler
    dd interrupt_0x0C_handler
    dd interrupt_0x0D_handler
    dd interrupt_0x0E_handler
    dd interrupt_0x0F_handler
    dd interrupt_0x10_handler

    dd interrupt_0x11_handler
    dd interrupt_0x12_handler
    dd interrupt_0x13_handler
    dd interrupt_0x14_handler
    dd interrupt_0x15_handler
    dd interrupt_0x16_handler
    dd interrupt_0x17_handler
    dd interrupt_0x18_handler
    dd interrupt_0x19_handler
    dd interrupt_0x1A_handler
    dd interrupt_0x1B_handler
    dd interrupt_0x1C_handler
    dd interrupt_0x1D_handler
    dd interrupt_0x1E_handler
    dd interrupt_0x1F_handler

    dd interrupt_0x20_handler
    dd interrupt_0x21_handler
    dd interrupt_0x22_handler
    dd interrupt_0x23_handler
    dd interrupt_0x24_handler
    dd interrupt_0x25_handler
    dd interrupt_0x26_handler
    dd interrupt_0x27_handler
    dd interrupt_0x28_handler
    dd interrupt_0x29_handler
    dd interrupt_0x2A_handler
    dd interrupt_0x2B_handler
    dd interrupt_0x2C_handler
    dd interrupt_0x2D_handler
    dd interrupt_0x2E_handler
    dd interrupt_0x2F_handler

section .text

extern syscall_table
extern syscall_check

global syscall_handler
syscall_handler:
    push MAGIC
    push 0x80

    push ds
    push es
    push fs
    push gs
    pusha

    push 0x80

    push ebp
    push edi
    push esi
    push edx
    push ecx
    push ebx

    push eax
    call syscall_check
    pop eax

    call [syscall_table + eax * 4]

    add esp, (6 * 4)

    mov [esp + 8 * 4], eax

    jmp interrupt_exit